package pv.fbv3;

import java.util.Arrays;
import java.util.List;

import pv.fbv3.CustomCallback.LoginCallback;
import pv.fbv3.CustomCallback.PostCallback;
import pv.fbv3.CustomCallback.PublishCallback;
import pv.fbv3.CustomCallback.RequestAppCallback;
import pv.fbv3.CustomCallback.RequestInfoCallback;
import pv.util.CustomSimpleProgressDialog;
import pv.util.Utility;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.support.v4.app.Fragment;
import android.widget.TextView;
import android.widget.Toast;

import com.facebook.FacebookException;
import com.facebook.FacebookOperationCanceledException;
import com.facebook.Request;
import com.facebook.RequestAsyncTask;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.Session.StatusCallback;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.facebook.model.GraphUser;
import com.facebook.widget.WebDialog;
import com.facebook.widget.WebDialog.OnCompleteListener;

/**
 * This class help to login, update status, update photo... you must implement
 * in methods:
 * 
 * 
 * <p/>
 * <strong>onCreate</strong> on <strong>onCreate</strong>
 * <p/>
 * <strong>onResume</strong> on <strong>onResume</strong>
 * <p/>
 * <strong>onActivityResult</strong> on <strong>onActivityResult</strong>
 * <p/>
 * <strong>setFragment</strong> on <strong>onActivityCreated(if
 * fragment)</strong>
 * <p/>
 * <strong>onPause</strong> on <strong>onPause</strong>
 * <p/>
 * <strong>onDestroy</strong> <strong>on onDestroy</strong>
 * <p/>
 * 
 */
public class FacebookHelperv3 {
	private static final int FRIENDS_ACTIVITY = 1001;
	private static final int PLACE_ACTIVITY = 1002;

	protected UiLifecycleHelper uiHelper;
	protected UserInfoFB userInfo;
	protected Activity activity;
	protected Fragment fragment;
	protected StatusCallback callback = new LoginSuccessSession();
	protected LoginHelperv2 lh;
	protected static CustomSimpleProgressDialog dialog;
	protected Bundle params;
	protected CustomCallback listener;

	protected static FacebookHelperv3 instance = new FacebookHelperv3();

	protected FacebookHelperv3() {

	}

	public static synchronized FacebookHelperv3 getInstance() {
		return instance;
	}

	public void init(Activity activity) {
		this.activity = activity;
		Session session = new Session(activity);
		Session.setActiveSession(session);
		lh = new LoginHelperv2(activity);
		lh.setReadPermissions(Arrays.asList("email"));
		lh.setSessionStatusCallback(callback);
		userInfo = new UserInfoFB();
		listener = null;

	}

	/**
	 * init facebook helper with permission
	 * 
	 * @param activity
	 *            activity
	 * @param permissions
	 *            permissions to set
	 * @param isReadPermission
	 *            if read permission
	 * */

	public void init(Activity activity, List<String> permissions,
			boolean isReadPermission) {
		this.activity = activity;
		Session session = new Session(activity);
		Session.setActiveSession(session);
		lh = new LoginHelperv2(activity);
		if (isReadPermission) {
			lh.setReadPermissions(permissions);
		} else {
			lh.setPublishPermissions(permissions);
		}
		lh.setSessionStatusCallback(callback);
		userInfo = new UserInfoFB();
		listener = null;

	}

	/**
	 * set permission for publish
	 * 
	 * @param permissions
	 *            permission to set
	 * */
	public void setPublishPermissions(List<String> permissions) {
		lh.setPublishPermissions(permissions);

	}

	/**
	 * set permission for read
	 * 
	 * @param permissions
	 *            permission to set
	 * */
	public void setReadPermissions(List<String> permissions) {
		lh.setReadPermissions(permissions);

	}

	protected static synchronized void showDialog(Context context,
			AsyncTask asyncTask) {
		if (dialog == null || !dialog.isShowing())
			dialog = CustomSimpleProgressDialog.show(context, asyncTask);

	}

	protected static synchronized void dismissDialog() {
		if (dialog != null && dialog.isShowing())
			dialog.dismiss();

	}

	protected void onSessionStateChange(final Session session,
			SessionState state, Exception exception) {
		if (session != null && session.isOpened()) {
			// Get the user's data.
			makeMeRequest(session);
		}

	}

	protected void publishPhotoDialog(Bundle params, Bitmap bitmap) {

		Request request = Request.newUploadPhotoRequest(
				Session.getActiveSession(), bitmap, new Request.Callback() {

					@Override
					public void onCompleted(Response response) {
						// TODO Auto-generated method stub

						FacebookHelperv3.dismissDialog();
						String post_id = (String) response.getGraphObject()
								.asMap().get("post_id");
						String result = CustomCallback.RESULT_FAIL;
						if (post_id != null) {
							Toast.makeText(activity.getApplicationContext(),
									"Upload photos successfully",
									Toast.LENGTH_SHORT).show();
							result = CustomCallback.RESULT_SUCCESS;

						} else {
							Toast.makeText(activity.getApplicationContext(),
									"Upload photos failed", Toast.LENGTH_SHORT)
									.show();
						}
						if (listener != null) {
							try {
								((PublishCallback) listener).call(result);
							} catch (Exception e) {
								// TODO: handle exception

							}

						}

					}
				});
		RequestAsyncTask task = new RequestAsyncTask(request);
		FacebookHelperv3.showDialog(activity, task);
		task.execute();

	}

	protected void makeMeRequest(final Session session) {
		// Make an API call to get user data and define a
		// new callback to handle the response.
		Request request = Request.newMeRequest(session,
				new Request.GraphUserCallback() {
					@Override
					public void onCompleted(GraphUser user, Response response) {
						// If the response is successful
						String result = CustomCallback.RESULT_FAIL;
						if (session == Session.getActiveSession()) {
							try {
								if (user != null) {
									// Set the id for the ProfilePictureView
									// view that in turn displays the profile
									// picture.
									// Map<String, Object> map = response
									// .getGraphObject().asMap();
									//
									// String email = "";
									// if (map != null)
									// email = (String) map.get("email");
									userInfo.setFirtName(user.getFirstName());
									userInfo.setLastName(user.getLastName());
									userInfo.setMiddleName(user.getMiddleName());
									userInfo.setEmail((String) user
											.getProperty("email"));
									userInfo.setLink(user.getLink());
									userInfo.setUserName(user.getUsername());
									userInfo.setBirthday(user.getBirthday());
									updateView();
									result = CustomCallback.RESULT_SUCCESS;
								}

							} catch (Exception e) {
								// TODO: handle exception
								Utility.LogE(this.getClass(), e);
							}
						}
						if (response.getError() != null) {
							// Handle errors, will do so later.
							result = response.getError().getErrorMessage();
						}
						if (listener != null) {
							try {
								((RequestInfoCallback) listener).call(result);
							} catch (Exception e) {
								// TODO: handle exception

							}

						}
					}
				});

		request.executeAsync();
	}

	protected void sendRequestDialog(Bundle params) {

		WebDialog requestsDialog = (new WebDialog.RequestsDialogBuilder(
				activity, Session.getActiveSession(), params))
				.setOnCompleteListener(new OnCompleteListener() {

					@Override
					public void onComplete(Bundle values,
							FacebookException error) {
						String result = CustomCallback.RESULT_FAIL;
						if (error != null) {
							if (error instanceof FacebookOperationCanceledException) {
								Toast.makeText(
										activity.getApplicationContext(),
										"Request cancelled", Toast.LENGTH_SHORT)
										.show();
							} else {
								Toast.makeText(
										activity.getApplicationContext(),
										"Network Error", Toast.LENGTH_SHORT)
										.show();
							}
						} else {
							final String requestId = values
									.getString("request");
							if (requestId != null) {
								Toast.makeText(
										activity.getApplicationContext(),
										"Request sent", Toast.LENGTH_SHORT)
										.show();
								result = CustomCallback.RESULT_SUCCESS;
							} else {
								Toast.makeText(
										activity.getApplicationContext(),
										"Request cancelled", Toast.LENGTH_SHORT)
										.show();
							}
						}
						if (listener != null) {
							try {
								((RequestAppCallback) listener).call(result);
							} catch (Exception e) {
								// TODO: handle exception

							}
						}
					}

				}).build();
		requestsDialog.show();
	}

	protected void postToWall(String requestID, Bundle postParams) {
		Session session = Session.getActiveSession();

		if (session != null && requestID != null) {
			postParams.putString("to", requestID);
			WebDialog feedDialog = (new WebDialog.FeedDialogBuilder(activity,
					Session.getActiveSession(), params)).setOnCompleteListener(
					new OnCompleteListener() {

						@Override
						public void onComplete(Bundle values,
								FacebookException error) {
							String result = CustomCallback.RESULT_FAIL;
							if (error == null) {
								// When the story is posted, echo the success
								// and the post Id.
								final String postId = values
										.getString("post_id");
								if (postId != null) {
									Toast.makeText(activity,
											"Post Successfully!!",
											Toast.LENGTH_SHORT).show();
									result = CustomCallback.RESULT_SUCCESS;
								} else {
									// User clicked the Cancel button
									Toast.makeText(
											activity.getApplicationContext(),
											"Post cancelled",
											Toast.LENGTH_SHORT).show();
								}
							} else if (error instanceof FacebookOperationCanceledException) {
								// User clicked the "x" button
								Toast.makeText(
										activity.getApplicationContext(),
										"Post cancelled", Toast.LENGTH_SHORT)
										.show();
							} else {
								// Generic, ex: network error
								Toast.makeText(
										activity.getApplicationContext(),
										"Error posting story",
										Toast.LENGTH_SHORT).show();
							}
							if (listener != null) {
								try {
									((PostCallback) listener).call(result);
								} catch (Exception e) {
									// TODO: handle exception

								}
							}
						}

					}).build();
			feedDialog.show();

			// Request.Callback callback = new Request.Callback() {
			// public void onCompleted(Response response) {
			// FacebookHelperv2.dismissDialog();
			// FacebookRequestError error = response.getError();
			// if (error != null) {
			// Toast.makeText(activity.getApplicationContext(),
			// error.getErrorMessage(), Toast.LENGTH_SHORT)
			// .show();
			// } else {
			// JSONObject graphResponse = response.getGraphObject()
			// .getInnerJSONObject();
			// String postId = null;
			// try {
			// postId = graphResponse.getString("id");
			// } catch (JSONException e) {
			// Log.i(TAG, "JSON error " + e.getMessage());
			// }
			//
			// if (postId != null) {
			// Toast.makeText(activity.getApplicationContext(),
			// "Post Successfully!", Toast.LENGTH_LONG)
			// .show();
			// } else {
			// Toast.makeText(activity.getApplicationContext(),
			// "Post Failed!", Toast.LENGTH_LONG).show();
			// }
			//
			// }
			//
			// }
			// };
			//
			// Request request = new Request(session, requestID + "/feed",
			// postParams, HttpMethod.POST, callback);
			//
			// RequestAsyncTask task = new RequestAsyncTask(request);
			// FacebookHelperv2.showDialog(activity, task);
			// task.execute();
		}

	}

	protected void postToWallAfterGetFriend() {
		if (params != null) {
			DataComunicationFB dcFB = DataComunicationFB.getInstance();

			GraphUser selection = dcFB.getUser();
			String listUserID = selection.getId();
			if (listUserID != null /* && selection.size() > 0 */) {
				// listUserID += selection.get(0).getId();
				// for (int i = 0; i < selection.size() - 1; i++) {
				// listUserID = listUserID + ", "
				// + selection.get(i + 1).getId();
				// }
				params.putString("to", listUserID);
				publishFeedDialog(params);
			} else {
				Toast.makeText(activity, "No friends selected",
						Toast.LENGTH_LONG).show();
			}

			// postToWall(user.getId(), params);
		}

	}

	protected void publishFeedDialog(Bundle params) {

		WebDialog feedDialog = (new WebDialog.FeedDialogBuilder(activity,
				Session.getActiveSession(), params)).setOnCompleteListener(
				new OnCompleteListener() {

					@Override
					public void onComplete(Bundle values,
							FacebookException error) {
						String result = CustomCallback.RESULT_FAIL;
						if (error == null) {
							// When the story is posted, echo the success
							// and the post Id.
							final String postId = values.getString("post_id");
							if (postId != null) {
								result = CustomCallback.RESULT_SUCCESS;
								Toast.makeText(activity,
										"Update status successfully!",
										Toast.LENGTH_SHORT).show();
							} else {
								// User clicked the Cancel button
								Toast.makeText(
										activity.getApplicationContext(),
										"Publish cancelled", Toast.LENGTH_SHORT)
										.show();
							}
						} else if (error instanceof FacebookOperationCanceledException) {
							// User clicked the "x" button
							Toast.makeText(activity.getApplicationContext(),
									"Publish cancelled", Toast.LENGTH_SHORT)
									.show();
						} else {
							// Generic, ex: network error
							Toast.makeText(activity.getApplicationContext(),
									"Error posting story", Toast.LENGTH_SHORT)
									.show();
						}
						if (listener != null) {
							try {
								((PublishCallback) listener).call(result);
							} catch (Exception e) {
								// TODO: handle exception

							}
						}
					}

				}).build();
		feedDialog.show();
	}

	protected boolean checkFirst() {

		if (!isNetworkAvailable()) {
			new AlertDialog.Builder(activity)
					.setTitle("Warning")
					.setMessage("Please connect your device to internet!")
					.setPositiveButton("Setting",
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// TODO Auto-generated method stub
									dialog.dismiss();
									Intent intent = new Intent(
											Settings.ACTION_WIRELESS_SETTINGS);

									activity.startActivity(intent);

								}
							})

					.setNegativeButton(
							activity.getString(android.R.string.cancel),
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// TODO Auto-generated method stub
									dialog.dismiss();
								}
							}).show();

			return false;

		}
		if (!isLogin()) {
			new AlertDialog.Builder(activity)
					.setTitle("Warning")
					.setMessage("You must first log in!")
					.setPositiveButton(activity.getString(android.R.string.ok),
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// TODO Auto-generated method stub
									dialog.dismiss();
									login();

								}
							})

					.setNegativeButton(
							activity.getString(android.R.string.cancel),
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// TODO Auto-generated method stub
									dialog.dismiss();
								}
							}).show();
			return false;
		}

		return true;

	}

	protected void updateView() {
		// TODO Auto-generated method stub
		new Handler().post(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				if (userInfo.getTvFirtName() != null) {
					userInfo.getTvFirtName().setText(userInfo.getFirtName());
				}
				if (userInfo.getTvLastName() != null) {
					userInfo.getTvLastName().setText(userInfo.getLastName());
				}
				if (userInfo.getTvEmail() != null) {
					userInfo.getTvEmail().setText(userInfo.getEmail());
				}

			}
		});
	}

	protected boolean isNetworkAvailable() {
		ConnectivityManager connectivityManager = (ConnectivityManager) activity
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = connectivityManager
				.getActiveNetworkInfo();
		return activeNetworkInfo != null && activeNetworkInfo.isConnected();
	}

	/**
	 * main event for facebook must implement them
	 * 
	 * 
	 */
	public void onCreate(Bundle savedInstanceState) {
		uiHelper = new UiLifecycleHelper(activity, callback);
		uiHelper.onCreate(savedInstanceState);

	}

	public void onResume() {
		uiHelper.onResume();
		// lh.startTracking();
	}

	public void onActivityResult(int requestCode, int resultCode, Intent data) {

		uiHelper.onActivityResult(requestCode, resultCode, data);
		lh.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case FRIENDS_ACTIVITY:
			if (resultCode == Activity.RESULT_OK) {
				postToWallAfterGetFriend();
			}

			break;
		default:
			break;
		}

	}

	public boolean notYetLogin() {
		Session session = Session.getActiveSession();
		return session != null
				&& session.getState().equals(SessionState.CREATED_TOKEN_LOADED);
	}

	public void onPause() {
		uiHelper.onPause();
		// lh.endTracking();
	}

	public void onDestroy() {
		uiHelper.onDestroy();
		listener = null;
	}

	public void onSaveInstanceState(Bundle outState) {
		uiHelper.onSaveInstanceState(outState);
	}

	/**
	 * END main event for facebook
	 * */
	public void requestUserInfo() {
		Session session = Session.getActiveSession();
		if (session != null && session.isOpened()) {
			// Get the user's data
			makeMeRequest(session);
		}
	}

	public UserInfoFB getUserInfo() {
		return userInfo;
	}

	public boolean isLogin() {

		return lh.isLogin();
	}

	public void login() {
		if (isNetworkAvailable())
			lh.login();
	}

	public void sendRequestApp(String string) {
		// TODO Auto-generated method stub
		if (checkFirst()) {
			Bundle params = new Bundle();
			params.putString("message", string);
			sendRequestDialog(params);
		}

	}

	public void postStatus(String caption, String description, String picture,
			String message, String link, String name) {
		if (checkFirst()) {
			Bundle params = new Bundle();
			params.putString("name", name);
			params.putString("caption", caption);
			params.putString("message", message);
			params.putString("description", description);
			params.putString("link", link);
			params.putString("picture", picture);
			publishFeedDialog(params);
		}

	}

	public void publishPhoto(String caption, Bitmap bitmap) {
		if (checkFirst()) {
			Bundle params = new Bundle();
			// ImageHelper ih = ImageHelper.getInstance();
			params.putString("caption", caption);
			publishPhotoDialog(params, bitmap);
		}
	}

	// public void postToFriendsWall(String caption, String description,
	// String picture, String message, String link, String name) {
	// if (checkFirst()) {
	// params = new Bundle();
	// params.putString("name", name/* "Facebook SDK for Android" */);
	// params.putString("caption", caption
	// /* "Build great social apps and get more installs." */);
	// params.putString("description", description
	// /*
	// "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps."
	// */);
	// params.putString("link", link/* "https://developers.facebook.com/android"
	// */);
	// params.putString("picture", picture/*
	// "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png"
	// */);
	//
	// Intent intent = new Intent(activity, PickFriendsActivity.class);
	// this.fragment.startActivityForResult(intent, FRIENDS_ACTIVITY);
	// }
	// }

	public void setFragment(Fragment fragment) {
		// TODO Auto-generated method stub
		lh.setFragment(fragment);
		this.fragment = fragment;
	}

	public void checkIn() {
		// LocationManager lm = null;
		// boolean gps_enabled, network_enabled;
		// if (lm == null)
		// lm = (LocationManager) activity
		// .getSystemService(Context.LOCATION_SERVICE);
		// try {
		// gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
		// } catch (Exception ex) {
		// }
		// try {
		// network_enabled = lm
		// .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
		// } catch (Exception ex) {
		// }
		//
		// if (!gps_enabled && !network_enabled) {
		// AlertDialog alertDialog = new AlertDialog.Builder(
		// activity.getApplicationContext()).setMessage(activity.getResources().getString(
		// R.string.gps_network_not_enabled)).setPositiveButton(
		// activity.getResources().getString(
		// R.string.open_location_settings),
		// new DialogInterface.OnClickListener() {
		//
		// @Override
		// public void onClick(
		// DialogInterface paramDialogInterface,
		// int paramInt) {
		// // TODO Auto-generated method stub
		// Intent myIntent = new Intent(
		// Settings.ACTION_SECURITY_SETTINGS);
		// activity.startActivity(myIntent);
		// // get gps
		// }
		// })
		// .setNegativeButton(
		// activity.getString(android.R.string.cancel),
		// new DialogInterface.OnClickListener() {
		//
		// @Override
		// public void onClick(
		// DialogInterface paramDialogInterface,
		// int paramInt) {
		// // TODO Auto-generated method stub
		//
		// }
		// })
		// .show();
		//
		// }
	}

	public void setTextViewFirtName(TextView tv) {
		if (userInfo != null) {
			userInfo.setTvFirtName(tv);

		}
	}

	public void setTextViewLastName(TextView tv) {
		if (userInfo != null) {
			userInfo.setTvLastName(tv);

		}
	}

	public void setTextViewEmail(TextView tv) {
		if (userInfo != null) {
			userInfo.setTvEmail(tv);

		}
	}

	public void setListener(CustomCallback listener) {
		this.listener = listener;
	}

	class LoginSuccessSession implements StatusCallback {

		@Override
		public void call(Session session, SessionState state,
				Exception exception) {
			// TODO Auto-generated method stub
			onSessionStateChange(session, state, exception);
			if (listener != null && listener instanceof LoginCallback
					&& state != null && state.isOpened()) {
				try {
					((LoginCallback) listener)
							.call(CustomCallback.RESULT_SUCCESS);
				} catch (Exception e) {
					// TODO: handle exception
				}

			}
		}
	}

	public void logout() {
		// TODO Auto-generated method stub
		if (lh != null)
			lh.logout();

	}

}
